﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;

namespace tao11.sdk
{
    public class Tao11Server
    {
        private string secret { get; set; }
        public string Appid { get; set; }
        public string Version { get; } = "2.0";
        /// <summary>
        /// 两服务器时间最大误差（分钟）
        /// </summary>
        public int Timeout { get; set; } = 10;

        public void SetSecret(string _secret)
        {
            this.secret = _secret;
        }
        /// <summary>
        /// 数据签名
        /// </summary>
        /// <param name="args">发送的数据</param>
        /// <returns></returns>
        public string Signature(System.Collections.Specialized.NameValueCollection args)
        {
            List<string> _list = new List<string>();
            foreach (var item in args.AllKeys)
            {
                if (item == "signature" || string.IsNullOrEmpty(args[item]))
                {
                    continue;
                }
                _list.Add(string.Format("{0}={1}", item, args[item]));
            }
            var _list_array = _list.ToArray();
            Array.Sort(_list_array);
            var s = string.Join("&", _list_array) + secret;

            byte[] result = Encoding.UTF8.GetBytes(s);
            MD5 md5 = new MD5CryptoServiceProvider();
            byte[] output = md5.ComputeHash(result);
            return BitConverter.ToString(output).Replace("-", "");  //tbMd5pass为输出加密文本的文本框
        }
        private object Handle(System.Collections.Specialized.NameValueCollection args)
        {
            string sign = "", remote_sign = "";
            sign = Signature(args);
            remote_sign = args["signature"];
            if (sign.ToLower() != remote_sign.ToLower())
            {
                throw new @base.Tao11Exception(1, "signature error.");
            }
            var time = args["time"];
            if (string.IsNullOrWhiteSpace(time)) time = "0";
            var tao11_time = 0;
            int.TryParse(time, out tao11_time);
            if (Math.Abs(DateTime.Now.ToUnix() - tao11_time) > Timeout * 60)
            {
                throw new @base.Tao11Exception(4, "request timeout.");
            }
            if (Version != args["version"])
            {
                throw new @base.Tao11Exception(6, "not support ver.");
            }
            var method = args["method"];
            if (string.IsNullOrWhiteSpace(method))
            {
                throw new @base.Tao11Exception(2, "method is empty.");
            }
            var body_string = args["body"];
            if (string.IsNullOrWhiteSpace(body_string))
            {
                throw new @base.Tao11Exception(2, "body is empty.");
            }
            string tb_user = args["tb_username"];
            switch (method)
            {
                case "tao11.taobao.user.get":
                    {
                        if (OnUserGet != null)
                        {
                            return new { success = true, data = OnUserGet(tb_user) };
                        }
                        break;
                    }
                case "tao11.taobao.copy.items":
                    {

                        if (OnCopyItem != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<@base.CopyGroup>(body_string);
                            OnCopyItem(tb_user, body);
                            return new { success = true };
                        }
                        break;
                    }
                case "tao11.taobao.copy.shop":
                    {

                        if (OnCopyItem != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<@base.CopyShop>(body_string);
                            OnCopyShop(tb_user, body);
                            return new { success = true };
                        }
                        break;
                    }
                case "tao11.taobao.query.task":
                    {

                        if (OnQueryTask != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<@base.QueryTask>(body_string);
                            return new { success = true, items = OnQueryTask(tb_user, body.group_id, body.tasks) };
                        }
                        break;
                    }
                case "tao11.taobao.query.items":
                    {
                        if (OnQueryItems != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(body_string);
                            return new { success = true, items = OnQueryItems(tb_user, body) };
                        }
                        break;
                    }
                case "tao11.taobao.query.items.state":
                    {
                        if (OnQueryItems != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<@base.ItemState>(body_string);
                            return new { success = true, items = OnQueryItemsByState(tb_user, body) };
                        }
                        break;
                    }
                case "tao11.taobao.items.update":
                    {
                        if (OnUpdateItem != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<@base.ItemUpdate>(body_string);
                            return new { success = true, items = OnUpdateItem(tb_user, body.action, body.items) };
                        }
                        break;
                    }
                case "tao11.taobao.items.maps.create":
                    {
                        if (OnCreateItemMap != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<@base.ItemMap[]>(body_string);
                            OnCreateItemMap(tb_user, body);
                            return new { success = true };
                        }
                        break;
                    }
                case "tao11.taobao.query.map.state":
                    {
                        if (OnQueryMapByState != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<@base.ItemState>(body_string);
                            return new { success = true, items = OnQueryMapByState(tb_user, body) };
                        }
                        break;
                    }
                case "tao11.taobao.query.map":
                    {
                        if (OnQueryMap != null)
                        {
                            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<string[]>(body_string);
                            return new { success = true, items = OnQueryMap(tb_user, body) };
                        }
                        break;
                    }
                default:
                    {
                        throw new @base.Tao11Exception(3, "method not exists.");
                    }
            }
            return null;
        }
        public void In(System.Web.HttpRequest Request, System.Web.HttpResponse Response, System.Web.HttpContext Context)
        {
            try
            {
                object result = null;
                if (Request.HttpMethod == "GET")
                {
                    result = Handle(Request.QueryString);
                }
                else if (Request.HttpMethod == "POST")
                {
                    result = Handle(Request.Form);
                }
                else
                {
                    Response.WriteJson(new { success = false, err = new { code = 9, message = "http-method error." } });
                    return;
                }
                if (result != null)
                {
                    Response.WriteJson(result);
                    return;
                }
            }
            catch (@base.Tao11Exception e)
            {
                Response.WriteJson(new { success = false, err = new { code = e.Code, message = e.Message } });
                return;
            }
            catch (Exception e)
            {
                Response.WriteJson(new { success = false, err = new { code = 9, message = e.Message } });
                return;
            }

        }
        public void In(System.Web.HttpRequestBase Request, System.Web.HttpResponseBase Response, System.Web.HttpContextBase Context)
        {
            try
            {
                object result = null;
                if (Request.HttpMethod == "GET")
                {
                    result = Handle(Request.QueryString);
                }
                else if (Request.HttpMethod == "POST")
                {
                    result = Handle(Request.Form);
                }
                else
                {
                    Response.WriteJson(new { success = false, err = new { code = 9, message = "http-method error." } });
                    return;
                }
                if (result != null)
                {
                    Response.WriteJson(result);
                    return;
                }
            }
            catch (@base.Tao11Exception e)
            {
                Response.WriteJson(new { success = false, err = new { code = e.Code, message = e.Message } });
                return;
            }
            catch (Exception e)
            {
                Response.WriteJson(new { success = false, err = new { code = 9, message = e.Message } });
                return;
            }
        }
        /// <summary>
        /// 回调复制任务状态
        /// </summary>
        /// <param name="callbackurl"></param>
        /// <param name="items"></param>
        public result.CopyUpdateResponse UpdateCopyState(string callbackurl, IEnumerable<result.CopyResult> items)
        {
            System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
            var values = new System.Collections.Specialized.NameValueCollection();
            values["appid"] = Appid;
            values["time"] = DateTime.Now.ToUnix().ToString();
            values["method"] = "tao11.taobao.update.copy";
            values["tb_username"] = "";
            values["body"] = "";
            values["version"] = Version;
            values["signature"] = Signature(values);
            List<KeyValuePair<String, String>> paramList = new List<KeyValuePair<String, String>>();
            foreach(var key in values.AllKeys)
            {
                paramList.Add(new KeyValuePair<string, string>(key,values[key]));
            }
            var response = client.PostAsync(callbackurl, new FormUrlEncodedContent(paramList)).Result;
            var result = response.Content.ReadAsStringAsync().Result;
            var body = Newtonsoft.Json.JsonConvert.DeserializeObject<sdk.result.CopyUpdateResponse>(result);
            return body;
            //throw new NotImplementedException();
        }
        /// <summary>
        /// 回调复制任务状态
        /// </summary>
        /// <param name="callbackurl"></param>
        /// <param name="item"></param>
        /// <returns></returns>
        public result.CopyUpdateResponse UpdateCopyState(string callbackurl, result.CopyResult item)
        {
            return UpdateCopyState(callbackurl, new result.CopyResult[] { item });
        }
        /// <summary>
        /// tao11.taobao.user.get
        /// </summary>
        public Func<string, result.ServiceDateRange> OnUserGet { get; set; }
        /// <summary>
        /// tao11.taobao.copy.items
        /// </summary>
        public Action<string, @base.CopyGroup> OnCopyItem { get; set; }
        /// <summary>
        /// tao11.taobao.copy.shop
        /// </summary>
        public Action<string, @base.CopyShop> OnCopyShop { get; set; }
        /// <summary>
        /// tao11.taobao.query.task
        /// </summary>
        public Func<string, string, IEnumerable<string>, IEnumerable<result.CopyResult>> OnQueryTask { get; set; }
        /// <summary>
        /// tao11.taobao.query.items
        /// </summary>
        public Func<string, IEnumerable<string>, IEnumerable<result.ItemInfo>> OnQueryItems { get; set; }
        /// <summary>
        /// tao11.taobao.query.items.state
        /// </summary>
        public Func<string, @base.ItemState, IEnumerable<result.ItemInfo>> OnQueryItemsByState { get; set; }
        /// <summary>
        /// tao11.taobao.items.update
        /// </summary>
        public Func<string, @base.ItemAction, IEnumerable<string>, IEnumerable<result.ItemUpdateResult>> OnUpdateItem { get; set; }
        /// <summary>
        /// tao11.taobao.items.maps.create
        /// </summary>
        public Action<string, IEnumerable<@base.ItemMap>> OnCreateItemMap { get; set; }
        /// <summary>
        /// tao11.taobao.query.map.state
        /// </summary>
        public Func<string, @base.ItemState, IEnumerable<@base.ItemMap>> OnQueryMapByState { get; set; }
        /// <summary>
        /// tao11.taobao.query.map
        /// </summary>
        public Func<string, IEnumerable<string>, IEnumerable<@base.ItemMap>> OnQueryMap { get; set; }
        public static Tao11Server Current { get; private set; }
        static Tao11Server()
        {
            Current = new Tao11Server();
        }
    }


}
